import CryptoJS from 'crypto-js'
import NodeRSA from 'node-rsa'

//AES和RSA加密混淆算法
export function encryptAesAndRsa (data) {
  let content = JSON.stringify(data)

  //明文补位
  let plaintext = str2UTF8(content)
  let plaintextLength = plaintext.length
  if(plaintextLength % 16 !== 0) {
    plaintextLength += 16 - plaintextLength % 16
    let bytes = new Array(plaintextLength)
    let i =plaintextLength
    while(i--){
      bytes[i] = 0
    }

    for (let j = 0; j < plaintextLength; j++){
      if ( j < plaintext.length ) {
        bytes[j] = plaintext[j]
      }
    }
    plaintext = bytes
    content = byteToString (plaintext)
  }

  let randomKey = randomString(16)

  let encryptKey = CryptoJS.enc.Utf8.parse(randomKey)
  //base64后的key 解密和测试用
  // let key = CryptoJS.enc.Utf8.parse(CryptoJS.enc.Base64.stringify(encryptKey))
  // console.log("key：" + CryptoJS.enc.Base64.stringify(encryptKey))

  //AES加密明文内容
  let encryptedData = CryptoJS.AES.encrypt(content, encryptKey, {iv: encryptKey, mode : CryptoJS.mode.CBC, padding : CryptoJS.pad.NoPadding})
  let encryptedStr = encryptedData.toString()

  //RSA加密AES密钥
  let aesKey = encryptRsa (CryptoJS.enc.Base64.stringify(encryptKey))

  //混淆密文和密钥
  let len = encryptedStr.length>100?100:encryptedStr.length
  let inputIndex = Math.ceil(Math.random()*len)
  let indexInfo = `${inputIndex}/${aesKey.length}`
  let indexBase64 =  CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(indexInfo))
  let str1 = encryptedStr.substring(0,inputIndex)
  let str2 = encryptedStr.substring(inputIndex)
  let garbleContent = indexBase64 + '/' + str1 + aesKey + str2
  return garbleContent
}

//RSA加密
function encryptRsa (keyRsa){
  let clientKey = new NodeRSA()
  clientKey.setOptions({encryptionScheme: 'pkcs1'})
  clientKey.importKey('-----BEGIN PUBLIC KEY-----\n' + public_key + '\n-----END PUBLIC KEY-----')
  let encryptedR = clientKey.encrypt(keyRsa,'base64')
  return encryptedR.toString()
}

//随机生成字符串
function randomString (len) {
  let charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let randomString = ''
  for (let i = 0; i < len; i++) {
    let randomPoz = Math.floor(Math.random() * charSet.length)
    randomString += charSet.substring(randomPoz,randomPoz+1)
  }
  return randomString
}

//AES和RSA解密混淆算法
export function decryptAesAndRsa (data) {
  let content = JSON.stringify(data).replace(/"/g,'')
  let index = content.indexOf("/")
  let indexBase64 = content.substring(0, index)
  let indexInfo = CryptoJS.enc.Base64.parse(indexBase64).toString(CryptoJS.enc.Utf8)
  let indexInfos = indexInfo.split("/")
  let inputIndex = parseInt(indexInfos[0], 10)
  let length = parseInt(indexInfos[1], 10)
  let startIndex = inputIndex + indexBase64.length + 1
  //RSA加密后的AES密钥
  let keyRsa = content.substring(startIndex, startIndex + length)
  //AES加密后的内容
  let contentAes = content.substring(indexBase64.length + 1, startIndex) + content.substring(startIndex + length)
  //通过RSA解密出密钥
  let aesKey = decryptRsa(keyRsa)
  //通过AES密钥解密
  let plainText = decryptAes(aesKey, contentAes)
  return plainText
}

//字符串转bytes
function str2UTF8 (str){
  let bytes = []
  let len,c
  len = str.length
  for(let i = 0; i < len; i++){
    c = str.charCodeAt(i)
    if(c >= 0x010000 && c <= 0x10FFFF){
      bytes.push(((c >> 18) & 0x07) | 0xF0)
      bytes.push(((c >> 12) & 0x3F) | 0x80)
      bytes.push(((c >> 6) & 0x3F) | 0x80)
      bytes.push((c & 0x3F) | 0x80)
    }else if(c >= 0x000800 && c <= 0x00FFFF){
      bytes.push(((c >> 12) & 0x0F) | 0xE0)
      bytes.push(((c >> 6) & 0x3F) | 0x80)
      bytes.push((c & 0x3F) | 0x80)
    }else if(c >= 0x000080 && c <= 0x0007FF){
      bytes.push(((c >> 6) & 0x1F) | 0xC0)
      bytes.push((c & 0x3F) | 0x80)
    }else{
      bytes.push(c & 0xFF)
    }
  }
  return bytes
}

//bytes转String
function byteToString (arr) {
  if(typeof arr === 'string') {
    return arr
  }
  let str = '',
    _arr = arr
  for(let i = 0; i < _arr.length; i++) {
    let one = _arr[i].toString(2),
      v = one.match(/^1+?(?=0)/)
    if(v && one.length === 8) {
      let bytesLength = v[0].length
      let store = _arr[i].toString(2).slice(7 - bytesLength)
      for(let st = 1; st < bytesLength; st++) {
        store += _arr[st + i].toString(2).slice(2)
      }
      str += String.fromCharCode(parseInt(store, 2))
      i += bytesLength - 1
    } else {
      str += String.fromCharCode(_arr[i])
    }
  }
  return str
}

//RSA解密
function decryptRsa (keyRsa){
  let clientKey = new NodeRSA()
  clientKey.importKey('-----BEGIN PUBLIC KEY-----\n' + public_key + '\n-----END PUBLIC KEY-----')
  let encryptedR = clientKey.decryptPublic(keyRsa,'utf8')
  //由于填充模式补位了多个空值，这里进行移除，需要优化
  let arr = str2UTF8(encryptedR).slice(100)
  let toStr = byteToString(arr)
  return toStr.toString()
}

//AES解密
function decryptAes (aesKey,contentAes){
  // 将base64的key转成128bit，contentAes必须是base64
  let key = CryptoJS.enc.Base64.parse(aesKey)
  let plainText = CryptoJS.AES.decrypt(contentAes,key,{iv: key, mode : CryptoJS.mode.CBC, padding : CryptoJS.pad.NoPadding})
  let returnStr = plainText.toString(CryptoJS.enc.Utf8)
  //由于填充模式补位了多个空值，这里进行移除，需要优化
  let arr = str2UTF8(returnStr).slice(0,-10)
  let toStr = byteToString(arr)
  return toStr.toString()
}

var public_key = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDFz+Ysb0uThqfTpMFRQV28fmEybJq/YwkWcfHKRQJpN6L7IVdidS5mY2kUJ5L6bk0o2eweVtEhrCU2E1tfhmA1YDMa63YdShmyVSv/As8gS5eaXd1G32JGlDs22mlJ4TD/JlCkK8o9bBTcRwYmFeEMZcQJzlpG14OoaO+TvSau6wIDAQAB'